
import socket  # from socket import *
from multiprocessing import Process
import signal

import dict_db

HOST = '0.0.0.0'
PORT = 5000
ADDR = (HOST, PORT)

class ClientProcess(Process):
    def __init__(self, client_socket, db):
        super().__init__()
        self.client_socket = client_socket
        self.db = db
        # username 用保存用登录的用户名,如果用户已经登录
        # self.user_name 绑定用户名, 否则
        # self.user_name 绑定 None
        self.user_name = None

    def run(self):
        # 为每个进程创建一个独立的游标
        self.db.create_cursor()
        print('client Connected....')
        # 接受并处理客户端的信息
        while True:
            data = self.client_socket.recv(1024).decode()
            if not data:  # 链接中断
                break
            package = data.split('\t')  # ['L', 'weimz', '123456']
            code = package[0]
            if code == 'E':   # 退出登录
                print('用户', self.user_name, '退出登录')
                self.user_name = None
            elif code == 'R':  # 注册
                self.register(package[1], package[2])
            elif code == 'L':  # 登录
                self.login(package[1], package[2])
            elif code == 'Q':  # 查单词
                self.query_word(package[1])
            elif code == 'H':  # 查看查词历史
                self.query_history()

        print("进程退出")
        self.db.close_cursor()
        self.client_socket.close()

    def register(self, username, password):
        if self.db.add_user(username, password):
            print('用户', username, '注册成功')
            self.client_socket.send(b'T')
        else:
            print('用户', username, '注册失败')
            self.client_socket.send(b'F')

    def login(self, username, password):
        if self.db.check_user(username, password):
            self.user_name = username  # 记住用户的登录用户名
            self.client_socket.send(b'T')
            print('用户', username, '登录成功')
        else:
            self.client_socket.send(b'F')
            print('用户', username, '登录失败')

    def query_word(self, word):
        trans = self.db.query_word(word)
        if trans:
            self.client_socket.send(b'T\t' + trans.encode())
            self.db.insert_hist(self.user_name, word)
        else:
            self.client_socket.send(b'F')

    def query_history(self):
        # 先验证用户是否登录，如果没有登录返回 b'F'
        if self.user_name:
            self.client_socket.send(
                b'T\t'+ self.db.get_hist(self.user_name).encode())
        else:
            self.client_socket.send(b'F')
def main():
    db = dict_db.DictDB()
    server_socket = socket.socket()
    server_socket.setsockopt(
        socket.SOL_SOCKET,
        socket.SO_REUSEADDR,
        1)
    server_socket.bind(ADDR)
    server_socket.listen(5)
    print('listen the port 5000.....')
    # 处理僵尸进程
    signal.signal(signal.SIGCHLD, signal.SIG_IGN)
    while True:  # 循环接受客户端链接
        try:
            c, addr = server_socket.accept()
            print('客户端', addr, '已连接...')
        except KeyboardInterrupt:  # ctrl + c
            server_socket.close()
            return
        except Exception as err:
            print("err:", err)
            continue
        # 创建子进程对象，处理客户端的请求
        p = ClientProcess(c, db)
        p.daemon = True
        p.start()


if __name__ == '__main__':
    main()